home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / opbonus.arc / MEGAPAGE.ARC / MEGAPAGE.PAS < prev   
Pascal/Delphi Source File  |  1991-03-20  |  23KB  |  720 lines

  1. { --------------------------------------------------------------------------
  2.  
  3.                    MEGAPAGE v1.00 - Copyright 1990 Scott Samet
  4.  
  5.                         FidoNet 1:135/990   CI$ 70671,213
  6.  
  7.   --------------------------------------------------------------------------
  8.  
  9.   This program enhances the TurboPower Software Object Professional POPHELP
  10.   screens.  It adds the OPRO manual page numbers to the help screens, so
  11.   it's easier to look up the full information.
  12.  
  13.   To run this program, you need the OPRO.TXT file, the various OPxxxxx.TXT
  14.   files, and the INDEX and INDEX2 files.  All these files are provided with
  15.   OPRO.  For my version of OPRO, they are located in INDEX.LZH on the BONUS
  16.   disk.  The program will read these files and create updated files ending
  17.   with  "NEW".   None of the original files are altered.
  18.  
  19.   It takes about 200k of available memory to run MEGAPAGE.   A run time
  20.   error 203 indicates more memory is needed.
  21.  
  22.   After running MEGAPAGE, execute "MAKEHELP OPRO.NEW" to compile the updated
  23.   files and create an enhanced OPRO.HLP file.   Reload POPHELP so it uses the
  24.   new file.
  25.  
  26.   -------------------------------------------------------------------------
  27.  
  28.                                       Notes
  29.  
  30.   By default, the program builds a list of identifers that appear in the
  31.   INDEX and INDEX2 files that do NOT appear in the help files.  It creates
  32.   an extra help file, OPXXXXXX.NEW, for these identifiers.  This information
  33.   is sketchy at best, but it is better than nothing, and does point you to
  34.   the correct place in the manual.
  35.  
  36.   You may disable this feature by using the /N switch on the command line.
  37.  
  38.   ------------------------------------------------------------------------
  39.  
  40.                               Technical Description
  41.  
  42.   The program reads the INDEX and INDEX2 files.  For each index reference,
  43.   it creates a record on the heap, indexed by the identifier.  If the
  44.   identifier is duplicated (like Init), the index entry is flagged to show
  45.   that duplicates exist.  During this pass, an special index entry is made
  46.   for each unit and object name encountered.
  47.  
  48.   The index files are read a second time.  For identifiers flagged as
  49.   having duplicates, a second index entry is created.  This time, the
  50.   identifier is qualified by the Object or Unit name, "RawWindow.Init".
  51.  
  52.   Next, it reads the text of the entire help system.  !TOPIC statements
  53.   are located and the topic extracted.  If the topic does not match any
  54.   of the short identifiers, it is ignored.  If it matches an unduplicated
  55.   short identifier, the volume and page information is added to the help
  56.   text.
  57.  
  58.   If the topic matches a duplicated short identifier, like Init, it scans
  59.   the help text, searching for text that "looks like" the correct long
  60.   identifer.  This is only a guess, but it's a fairly good one.  If the
  61.   long identifer appears in the dictionary, the volume and page information
  62.   is added to the help text.
  63.  
  64.   As dictionary entry is matched by a help topic, it's flagged to show
  65.   that it's been used.
  66.  
  67.   After all the help text has been read, it makes one more pass over the
  68.   index files (unless the /N switch is present).  Each item is checked
  69.   against the dictionary to see if it was used.  Any item that was not used
  70.   is added to the special OPXXXXXX.NEW file.
  71.  
  72.   The program has a hard-coded check so items from OPCOLOR are not written
  73.   to the OPXXXXXX.  Since these items are (trivial) color names, like
  74.   RedOnBlack, there's no need to waste space on them.
  75.  
  76.   -------------------------------------------------------------------------
  77.  
  78.   Credit goes to Thom Foulks, Colorado Springs, for the original ADDPAGES
  79.   program that inspired MEGAPAGE.
  80.  
  81.   -------------------------------------------------------------------------}
  82.  
  83. {$M 16384,150000,655360}
  84.  
  85. Uses
  86.   DOS, OPCrt, OPRoot, OPString;
  87.  
  88. Const
  89.   VirginNo = '1.01';
  90.   BuffSize = 16384;
  91.  
  92. Type
  93.   RefPtr = ^RefRec;
  94.  
  95.   RefRec = Record
  96.     Volume:   Char;
  97.     Page:     Array [1..5] of Char;
  98.     Topic:    Word;
  99.     End;
  100.  
  101.   DeluxeStringDict = Object (StringDict)
  102.     Constructor InitCustom(PoolSize : Word);
  103.     end;
  104.  
  105.   { This constructor allocates the hash table to specified size, avoiding
  106.     heap fragmentation and delays caused by expanding on the fly. }
  107.   Constructor DeluxeStringDict.InitCustom(PoolSize : Word);
  108.     {-Allocate hash pool}
  109.   var
  110.     S : Word;
  111.   begin
  112.     sdUsed := 0;
  113.     sdPool := nil;
  114.     sdStatus := 0;
  115.  
  116.     if not Root.Init then
  117.       Fail;
  118.  
  119.     {Validate that PoolSize is a proper factor of two}
  120.     if (PoolSize > 8192) or (PoolSize < 8) then begin
  121.       Done;
  122.       InitStatus := epFatal+ecBadParam;
  123.       Fail;
  124.     end;
  125.     S := PoolSize;
  126.     while S > 1 do begin
  127.       if odd(S) then begin
  128.         Done;
  129.         InitStatus := epFatal+ecBadParam;
  130.         Fail;
  131.       end;
  132.       S := S shr 1;
  133.     end;
  134.  
  135.     if not GetMemCheck(sdPool, PoolSize*SizeOf(StringPtr)) then begin
  136.       Done;
  137.       InitStatus := epFatal+ecOutOfMemory;
  138.       Fail;
  139.     end;
  140.     FillChar(sdPool^, PoolSize*SizeOf(StringPtr), 0);
  141.     sdSize := PoolSize;
  142.   end;
  143.  
  144. Var
  145.   Dict:        DeluxeStringDict; {!!.01}
  146.   Bias:        Word;
  147.   ShortCnt:    Word;
  148.   LongCnt:     Word;
  149.   ObjCnt:      Word;
  150.   OrigMem:     LongInt;
  151.  
  152.   Procedure AllocTextBuff (Var F: Text; Size: LongInt);
  153.   Const
  154.     MaxSize = 65531;
  155.   Var
  156.     P:   Pointer;
  157.   Begin
  158.     If Size > MaxSize
  159.       Then Size := MaxSize;
  160.     Size := Size and (Not 511);
  161.     If Size <= 0
  162.       Then Exit;
  163.     Getmem (P, Size);
  164.     If P = Nil
  165.       Then Exit;
  166.     SetTextBuf (F, P^, Size);
  167.     End;
  168.  
  169.   Procedure FreeTextBuff (Var F: Text);
  170.   Begin
  171.     With TextRec (F) do
  172.       If BufPtr <> @Buffer
  173.         Then FreeMem (BufPtr, BufSize);
  174.     End;
  175.  
  176.   Procedure Abort (S: String);
  177.   Begin
  178.     Writeln (S);
  179.     Halt (255);
  180.     End;
  181.  
  182.   Procedure CheckOpen (FN: PathStr);
  183.   Begin
  184.     If InOutRes <> 0
  185.       Then Abort ('Unable to Open ' + FN + '; Error=' + Long2Str (IOResult));
  186.     End;
  187.  
  188.   Procedure LogLineNo (S: String; Var N: Word; Force: Boolean);
  189.   Begin
  190.     If Force or (N = 1) or (N mod 100 = 0)
  191.       Then Write (N:10, '   ', S);
  192.     If Force
  193.       Then Writeln
  194.       Else Write (^M);
  195.     Inc (N);
  196.     end;
  197.  
  198.   Procedure LoadRefs (FN1, FN2: PathStr);
  199.   Type
  200.     String31 = String[31];
  201.     String5  = String[5];
  202.   Var
  203.     CurrRef:   RefPtr;
  204.     RefFile:   Text;
  205.     Topic:     String31;
  206.     ILine:     String;
  207.     Pass:      Word;
  208.     LineCnt:   Word;
  209.  
  210.     Function MakeRef (Vol: Char; Pg: String5): RefPtr;
  211.     Var
  212.       Ref:   RefPtr;
  213.     Begin
  214.       New (Ref);
  215.       If Ref = Nil
  216.         Then RunError (203);
  217.       With Ref^ do Begin
  218.         Volume := Vol;
  219.         Move (Pg[1], Page, 5);
  220.         Topic  := 0;
  221.         End;
  222.       MakeRef := Ref;
  223.       End { MakeRef };
  224.  
  225.     Procedure TableRef (Vol: Char; Pg, Top, UnitName, ObjName: String31);
  226.     Var
  227.       Test:   RefPtr;
  228.       I:      Word;
  229.     Begin { TableRef }
  230.       Top := Trim (Top);
  231.       If Top = ''
  232.         Then Exit;
  233.       Pg  := LeftPad (Trim (Pg), 6);
  234.       Delete (Pg, 3, 1);
  235.       ObjName := Trim (ObjName);
  236.       UnitName := Trim (UnitName);
  237.       If (ObjName = '') or (ObjName[1] = '-')
  238.         Then If (UnitName = '') or (UnitName[1] = '-')
  239.           Then Begin
  240.             ObjName := '';
  241.             UnitName := '';
  242.             End
  243.           Else Begin
  244.             ObjName := UnitName;
  245.             UnitName := '';
  246.             end;
  247.       If Pass = 1
  248.         Then Begin { First Pass }
  249.           { Attempt to add to Short Dictionary }
  250.           If Dict.Member (Top, LongInt (Test))
  251.             Then If (Test <> Nil)
  252.               Then Begin
  253.                 { First Duplicate, Release RefRec }
  254.                 Dispose (Test);
  255.                 Dict.Update (Top, LongInt (Nil));
  256.                 End
  257.               Else { Additional duplicate - nothing }
  258.             Else Begin
  259.               { Unique reference - add to table }
  260.               Inc (ShortCnt);
  261.               Dict.Add (Top, LongInt (MakeRef (Vol, Pg)));
  262.               I := Dict.GetStatus;
  263.               If I = 10008
  264.                 Then RunError (203);
  265.               If (0 < I) and (I < 20000)
  266.                 Then Abort ('Unable to add ' + Top);
  267.               end;
  268.           { Add Object Name to Short Dictionary }
  269.           If Not Dict.Member (ObjName, LongInt (Test))
  270.             Then begin
  271.               Dict.Add (ObjName, LongInt (MakeRef (' ', '')));
  272.               I := Dict.GetStatus;
  273.               If I = 10008
  274.                 Then RunError (203);
  275.               If (0 < I) and (I < 20000)
  276.                 Then Abort ('Unable to add ' + ObjName);
  277.               If I = 0
  278.                 Then Inc (ObjCnt);
  279.               end;
  280.           end { First Pass }
  281.         Else Begin { Second Pass }
  282.           If (ObjName <> '') and (ObjName [1] <> '-')
  283.             Then If (Dict.Member (Top, LongInt (Test))) and (Test = Nil)
  284.               Then begin
  285.                 { Duplicate entries in short dictionary - create long entry }
  286.                 Inc (LongCnt);
  287.                 Dict.Add (ObjName + '.' + Top, LongInt (MakeRef (Vol, Pg)));
  288.                 I := Dict.GetStatus;
  289.                 If I = 10008
  290.                   Then RunError (203);
  291.                 If (0 < I) and (I < 20000)
  292.                   Then Abort ('Unable to add ' + ObjName + '.' + Top);
  293.                 end;
  294.           end { Second Pass };
  295.       End { TableRef };
  296.  
  297.   Begin { LoadRefs }
  298.     ShortCnt := 0;
  299.     LongCnt  := 0;
  300.     ObjCnt   := 0;
  301.  
  302.     Pass := 1;
  303.     Writeln;
  304.     Writeln ('Loading Identifiers:');
  305.     Assign (RefFile, FN1);
  306.     AllocTextBuff (RefFile, 2* BuffSize);
  307.     {$I-} Reset (RefFile); {$I+}
  308.     If IOResult <> 0
  309.       Then Abort ('Unable to open ' + FN1);
  310.     LineCnt := 1;
  311.     While Not Eof (RefFile) DO Begin
  312.       Readln (RefFile, ILine);
  313.       LogLineNo (FN1, LineCnt, False);
  314.       If ILine[1] = '{'
  315.         Then TableRef (ILine [2], Copy (ILine, 9, 6), Copy (ILine, 19, 28),
  316.                        Copy (ILine, 47, 8), Copy (ILine, 57, 255));
  317.       End;
  318.     Close (RefFile);
  319.     FreeTextBuff (RefFile);
  320.     LogLineNo (FN1, LineCnt, True);
  321.  
  322.     Assign (RefFile, FN2);
  323.     AllocTextBuff (RefFile, 2* BuffSize);
  324.     {$I-} Reset (RefFile); {$I+}
  325.     If IOResult <> 0
  326.       Then Abort ('Unable to open ' + FN2);
  327.     LineCnt := 1;
  328.     While Not Eof (RefFile) DO Begin
  329.       Readln (RefFile, ILine);
  330.       LogLineNo (FN2, LineCnt, False);
  331.       If ILine[1] = '{'
  332.         Then TableRef (ILine [2], Copy (ILine, 6, 6), Copy (ILine, 24, 28),
  333.                        Copy (ILine, 52, 8), Copy (ILine, 62, 255));
  334.       End;
  335.     Close (RefFile);
  336.     FreeTextBuff (RefFile);
  337.     LogLineNo (FN2, LineCnt, True);
  338.  
  339.     Pass := 2;
  340.     Writeln;
  341.     Writeln ('Loading non-unique identifiers:');
  342.     Assign (RefFile, FN1);
  343.     AllocTextBuff (RefFile, 2* BuffSize);
  344.     {$I-} Reset (RefFile); {$I+}
  345.     If IOResult <> 0
  346.       Then Abort ('Unable to open ' + FN1);
  347.     LineCnt := 1;
  348.     While Not Eof (RefFile) DO Begin
  349.       Readln (RefFile, ILine);
  350.       LogLineNo (FN1, LineCnt, False);
  351.       If ILine[1] = '{'
  352.         Then TableRef (ILine [2], Copy (ILine, 9, 6), Copy (ILine, 19, 28),
  353.                        Copy (ILine, 47, 8), Copy (ILine, 57, 255));
  354.       End;
  355.     Close (RefFile);
  356.     FreeTextBuff (RefFile);
  357.     LogLineNo (FN1, LineCnt, True);
  358.  
  359.     Assign (RefFile, FN2);
  360.     AllocTextBuff (RefFile, 2* BuffSize);
  361.     {$I-} Reset (RefFile); {$I+}
  362.     If IOResult <> 0
  363.       Then Abort ('Unable to open ' + FN2);
  364.     LineCnt := 1;
  365.     While Not Eof (RefFile) DO Begin
  366.       Readln (RefFile, ILine);
  367.       LogLineNo (FN2, LineCnt, False);
  368.       If ILine[1] = '{'
  369.         Then TableRef (ILine [2], Copy (ILine, 6, 6), Copy (ILine, 24, 28),
  370.                        Copy (ILine, 52, 8), Copy (ILine, 62, 255));
  371.       End;
  372.     Close (RefFile);
  373.     FreeTextBuff (RefFile);
  374.     LogLineNo (FN2, LineCnt, True);
  375.  
  376.     End { LoadRefs };
  377.  
  378.   Function FormatReference (Ref: RefRec): String;
  379.   Var
  380.     P:   String[6];
  381.   Begin
  382.     FormatReference := '';
  383.     With Ref do
  384.       If (Volume = '*')
  385.         Then FormatReference := ^M^J'Reference: Supplement'
  386.       Else If (Volume <> ' ')
  387.         Then Begin
  388.           P := Copy (Page, 3, 3);
  389.           While (Length (P) > 0) and (P[1] = '0') do Delete (P, 1, 1);
  390.           P := Copy (Page, 1, 2) + '-' + P;
  391.           If P[1] = ' '
  392.             Then Delete (P, 1, 1);
  393.           FormatReference := ^M^J'Reference: Vol ' + Volume + ', Pg ' + P;
  394.           end;
  395.     End;
  396.  
  397. Procedure ScanHelp (HelpFN, Ref1FN, Ref2FN: PathStr);
  398. var
  399.   MaxTopic:    Word;
  400.   MaxName:     String[12];
  401.   SaveTopic:   Word;
  402.  
  403.   Procedure ScanFile (FNIn: PathStr; NestLvl: Word);
  404.   Var
  405.     IFile:      Text;
  406.     OFile:      Text;
  407.     ILine:      String;
  408.     RefLine:    String;
  409.     Temp:       String;
  410.     ScanTop:    String;
  411.     Match:      RefPtr;
  412.     I:          Word;
  413.     J:          Word;
  414.     TopicNo:    Word;
  415.     SaveTopic:  Word;
  416.     FNOut:      PathStr;
  417.     CmdLine:    ^String;
  418.     LineNo:     Word;
  419.     ShowFN:     String[64];
  420.  
  421.     Procedure DoFixups (FN1, FN2, FNOut: PathStr; Var MaxTopic: Word);
  422.     Type
  423.       String31 = String[31];
  424.     Var
  425.       Ref:     RefPtr;
  426.       HFile:   Text;
  427.       RefFile: Text;
  428.       Top:     String [31];
  429.       ILine:   String;
  430.       LineNo:  Word;
  431.  
  432.       Procedure CheckRef (Top, UnitName, ObjName, Class: String31);
  433.       Var
  434.         CurrRef: RefPtr;
  435.         TempRef: RefPtr;
  436.       Begin
  437.         Top := Trim (Top);
  438.         If Top = ''
  439.           Then Exit;
  440.  
  441.         ObjName := Trim (ObjName);
  442.         UnitName := Trim (UnitName);
  443.         Class := Trim (Class);
  444.  
  445.         If (ObjName = '') or (ObjName[1] = '-')
  446.           Then If (UnitName = '') or (UnitName[1] = '-')
  447.             Then Begin
  448.               ObjName := '';
  449.               UnitName := '';
  450.               End
  451.             Else Begin
  452.               ObjName := UnitName;
  453.               UnitName := '';
  454.               If Class = 'Method'
  455.                 Then Class := 'Proc';
  456.               end;
  457.  
  458.         { Here we are quite arbitrary and throw away some things }
  459.  
  460.         If (StUpCase (ObjName) = 'OPCOLOR')
  461.           Then Exit;
  462.  
  463.         If Not Dict.Member (Top, LongInt (CurrRef))
  464.           Then CurrRef := Nil { not in short dictionary }
  465.           Else If CurrRef = Nil { in short dictionary, but duplicated }
  466.             Then If Not Dict.Member (Top, LongInt (CurrRef))
  467.               Then CurrRef := Nil; { not in long or short }
  468.  
  469.         If CurrRef <> Nil
  470.           Then With CurrRef^ do
  471.             If Topic = 0
  472.               Then Begin
  473.                 Class := Trim (Class);
  474.                 Inc (MaxTopic);
  475.                 Writeln (HFile, '!TOPIC ', MaxTopic, ' ', Top);
  476.                 Writeln (HFile, '!NOINDEX');
  477.  
  478.                 Write (HFile, ^B);
  479.  
  480.                 If ObjName <> ''
  481.                   Then If Dict.Member (ObjName, LongInt (TempRef)) and (TempRef <> NIL)
  482.                     Then With TempRef^ do
  483.                       Write (HFile, ^D, Topic, ^E, ObjName, ^E)
  484.                     Else Write (HFile, ObjName);
  485.  
  486.                 Case Class[1] of
  487.                   'D':
  488.                     If Class = 'Direct'
  489.                       Then Writeln (HFile, ' ', Top, ^B, ' (MAKEHELP Directive)')
  490.                       Else Writeln (HFile, ' ', Top, ^B, ' (Conditional Define)');
  491.                   'C':
  492.                     Writeln (HFile, '.', Top, ^B,' (Constant)');
  493.                   'T':
  494.                     If Class = 'TConst'
  495.                       Then Writeln (HFile, '.', Top, ^B, ' (Typed Constant)')
  496.                       Else Writeln (HFile, '.', Top, ^B, ' (Type)');
  497.                   'V':
  498.                     Writeln (HFile, '.', Top, ^B, ' (Variable)');
  499.                   'F':
  500.                     Writeln (HFile, '.', Top, ^B, ' (Field)');
  501.                   'E':
  502.                     Writeln (HFile, '.', Top, ^B, ' (Enumerated Type element)');
  503.                   'M':
  504.                     Writeln (HFile, '.', Top, ^B, ' (Method)');
  505.                   'P':
  506.                     Writeln (HFile, '.', Top, ^B, ' (Procedure/Function)');
  507.                   End;
  508.  
  509.                 If UnitName <> ''
  510.                   Then Begin
  511.                     Writeln (HFile);
  512.                     Write (HFile, 'See also:  ');
  513.                     If Dict.Member (UnitName, LongInt (TempRef)) and (TempRef <> NIL)
  514.                       Then With TempRef^ do
  515.                         Writeln (HFile, ^D, Topic, ^E, UnitName, ^E)
  516.                       Else Writeln (HFile, UnitName);
  517.                     End;
  518.  
  519.                 Writeln (HFile, FormatReference (CurrRef^));
  520.                 End;
  521.  
  522.         End { CheckRef };
  523.  
  524.     Begin { DoFixUps }
  525.       Writeln;
  526.       Writeln ('Building HELP text for missing items:');
  527.       Assign (HFile, FNOut);
  528.       AllocTextBuff (HFile, MaxAvail - 8192);
  529.       Rewrite (HFile);
  530.  
  531.       Assign (RefFile, FN1);
  532.       AllocTextBuff (RefFile, MaxAvail);
  533.       {$I-} Reset (RefFile); {$I+}
  534.       CheckOpen (FN1);
  535.       LineNo := 1;
  536.       While Not Eof (RefFile) DO Begin
  537.         Readln (RefFile, ILine);
  538.         LogLineNo (FN1, LineNo, False);
  539.         If ILine[1] = '{'
  540.           Then CheckRef (Copy (ILine, 19, 28), Copy (ILine, 47, 8),
  541.                          Copy (ILine, 57, 255), 'Method');
  542.         End;
  543.       Close (RefFile);
  544.       FreeTextBuff (RefFile);
  545.       LogLineNo (FN1, LineNo, True);
  546.  
  547.       Assign (RefFile, FN2);
  548.       AllocTextBuff (RefFile, MaxAvail);
  549.       {$I-} Reset (RefFile); {$I+}
  550.       CheckOpen (FN2);
  551.       LineNo := 1;
  552.       While Not Eof (RefFile) DO Begin
  553.         Readln (RefFile, ILine);
  554.         LogLineNo (FN2, LineNo, False);
  555.         If ILine[1] = '{'
  556.           Then CheckRef (Copy (ILine, 24, 28), Copy (ILine, 52, 8),
  557.                          Copy (ILine, 62, 255), Copy (ILine, 15, 8));
  558.         End;
  559.       Close (RefFile);
  560.       FreeTextBuff (RefFile);
  561.  
  562.       Close (HFile);
  563.       FreeTextBuff (HFile);
  564.       LogLineNo (FN2, LineNo, True);
  565.       End { DoFixups };
  566.  
  567.   Begin { ScanFile }
  568.     FNIn  := FExpand (FNIn);
  569.     FNOut := JustPathName (FNIn) + '\' + JustName (FNIn) + '.NEW';
  570.     ShowFN := LeftPad (JustFileName (FNIn), 12) + ' -> ' + JustFileName (FNOut);
  571.  
  572.     Assign (IFile, FNIn);
  573.     Assign (OFile, FNOut);
  574.     If NestLvl > 0
  575.       Then begin
  576.         AllocTextBuff (IFile, BuffSize);
  577.         AllocTextBuff (OFile, BuffSize);
  578.         end;
  579.     {$I-} Reset (IFile); {$I+}
  580.     CheckOpen (FNIn);
  581.     Rewrite (OFile);
  582.     CheckOpen (FNOut);
  583.  
  584.     ScanTop := '';
  585.     RefLine := '';
  586.     SaveTopic := 0;
  587.     LineNo    := 1;
  588.  
  589.     While Not Eof (IFile) DO Begin
  590.       Readln (IFile, ILine);
  591.       LogLineNo (ShowFN, LineNo, False);
  592.       Temp := StUpCase (ILine);
  593.       If (ILine <> '') and (Temp[1] = ';')
  594.         Then Begin
  595.           If RefLine <> ''
  596.             Then Writeln (OFile, RefLine);
  597.           RefLine := '';
  598.           End;
  599.       If Copy (Temp, 1, 6) = '!BIAS '
  600.         Then Begin
  601.           Val (Trim (Copy (Temp, 6, 255)), I, J);
  602.           If J = 0
  603.             Then Bias := I;
  604.           End
  605.       Else If Copy (Temp, 1, 9) = '!INCLUDE '
  606.         Then Begin
  607.           Temp := Trim (Copy (Temp, 10, 255));
  608.           ILine := Copy (ILine, 1, 9) + JustPathName (Temp) + JustName (Temp) + '.NEW';
  609.           ScanFile (Temp, NestLvl + 1);
  610.           End
  611.       Else If Copy (Temp, 1, 7) = '!TOPIC '
  612.         Then Begin
  613.           If RefLine <> ''
  614.             Then Writeln (OFile, RefLine);
  615.           RefLine := '';
  616.           ScanTop := '';
  617.           Temp := Trim (Copy (ILine, 8, 255));
  618.           I := Pos (' ', Temp);
  619.           If I > 0
  620.             Then Begin
  621.               Val (Copy (Temp, 1, I - 1), TopicNo, J);
  622.               Inc (TopicNo, Bias);
  623.               If (J = 0) and  (TopicNo > MaxTopic)
  624.                 Then SaveTopic := TopicNo;
  625.               Temp := Trim (Copy (Temp, I, 255));
  626.               If Dict.Member (Temp, LongInt (Match))
  627.                 Then If Match = Nil
  628.                   Then ScanTop := '.' + StUpCase (Temp)
  629.                   Else With Match^ do Begin
  630.                     RefLine := FormatReference (Match^);
  631.                     Topic := TopicNo;
  632.                     ScanTop := '';
  633.                     End;
  634.               End;
  635.           End
  636.       Else If (ScanTop <> '')
  637.         Then If (Pos (ScanTop, Temp) > 0)
  638.           Then begin
  639.             I := Pos (ScanTop, Temp);
  640.             J := I - 1;
  641.             If Temp [J] = ^E
  642.               Then Begin
  643.                 Delete (Temp, J, 1);
  644.                 Dec (J);
  645.                 end;
  646.             While (J > 0) and (Temp [J] in ['A'..'Z', 'a'..'z', '0'..'9', '.']) do dec (J);
  647.             While (I <= Length (Temp)) and (Temp [I] in ['A'..'Z', 'a'..'z', '0'..'9', '.']) do Inc (I);
  648.             Temp := Copy (Temp, J + 1, I - J - 1);
  649.             If Dict.Member (Temp, LongInt (Match))
  650.               Then With Match^ do Begin
  651.                 RefLine := FormatReference (Match^);
  652.                 Topic := TopicNo;
  653.                 ScanTop := '';
  654.                 end;
  655.             end;
  656.       Writeln (OFile, ILine);
  657.       End;
  658.     If RefLine <> ''
  659.       Then Writeln (OFile, RefLine);
  660.     Close (IFile);
  661.     LogLineNo (ShowFN, LineNo, True);
  662.     FreeTextBuff (IFile);
  663.     If SaveTopic > MaxTopic
  664.       Then begin
  665.         MaxTopic := SaveTopic;
  666.         MaxName  := JustName (FNIn);
  667.         end;
  668.  
  669.     If NestLvl = 0
  670.       Then Begin
  671.         Writeln (OFile, '; Maximum Topic is really ', MaxTopic, ' in ', MaxName);
  672.         CmdLine := Ptr (PrefixSeg, $80);
  673.         If Pos ('/N', StUpCase (CmdLine^)) = 0
  674.           Then begin
  675.             SaveTopic := MaxTopic;
  676.             DoFixups (Ref1FN, Ref2FN, 'OPXXXXXX.NEW', MaxTopic);
  677.             Writeln (OFile, '!INCLUDE OPXXXXXX.NEW');
  678.             Writeln (OFile, '; Maximum Generated Topic is ', MaxTopic);
  679.             End;
  680.  
  681.         Writeln;
  682.         Writeln ('Summary:');
  683.         Writeln (ShortCnt:10,           '  Identifiers');
  684.         Writeln (LongCnt:10,            '  Non-unique Identifers');
  685.         Writeln (ObjCnt:10,             '  Objects and Methods');
  686.         Writeln (OrigMem - MaxAvail:10, '  Bytes used for identifiers');
  687.         Writeln (MaxAvail:10,           '  Bytes left');
  688.         Writeln (SaveTopic:10,          '  Maximum Input  Topic Number (', MaxName, ')');
  689.         If Pos ('/N', StUpCase (CmdLine^)) = 0
  690.           Then Writeln (MaxTopic:10,    '  Maximum Output Topic Number (OPXXXXXX)');
  691.         Writeln;
  692.         Writeln ('Run MAKEHELP ', JustFileName (FNOut), ' to update OPRO.HLP');
  693.         end;
  694.  
  695.     Close (OFile);
  696.     FreeTextBuff (OFile);
  697.     End { ScanFile };
  698.  
  699. Begin { ScanHelp }
  700.   OrigMem  := MaxAvail;
  701.   Dict.InitCustom (8192);
  702.   LoadRefs (Ref1FN, Ref2FN);
  703.  
  704.   Bias     := 0;
  705.   MaxTopic := 0;
  706.   MaxName  := '';
  707.  
  708.   Writeln;
  709.   Writeln ('Converting Help files:');
  710.   ScanFile (HelpFN, 0);
  711.   End { ScanHelp };
  712.  
  713. Begin
  714.   Writeln ('MEGAPAGE - V', VirginNo, ' - Add index information to TurboPower POPHELP files');
  715.   Writeln ('Copyright 1990, Scott Samet');
  716.   ScanHelp ('OPRO.TXT', 'INDEX', 'INDEX2');
  717.   End.
  718.  
  719.  
  720.